//This file will contain functions that simply load settings.

//Code protected under GPL, see GPL.txt
//Copyright 2004 Chris Hilton
#ifndef SETTINGS_CC
#define SETTINGS_CC
#include <dirent.h>
#include <stdlib.h>
//#include "globals.h"
#include "settings.h"
#include "error.h"
#include "xml.h"
#include "simple.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

char **_str_name;
char **_str_data;
int _str_size = 0;


#define _STR_DB_MAX 20

struct extProgram {
	char *extension;
	char *action;
	struct extProgram *next;
};

int keyLen = 256;
char *_password;



int _mainWidth = 600;
int _mainHeight = 400;

int _treeDivider = 200;
unsigned char *_key;
char *_encryption_method;

char *_path;			//= getenv("HOME") + string("/MyJournal");

char *_confPath;		// = getenv("HOME") + "/.eLog/eLog.conf";

char *elog_set_current = NULL;
struct dict *elog_set_currentMeta = NULL;
struct extProgram *headExtention = NULL;
struct extProgram *_last = NULL;

int elog_set_mode_current = ELOG_SET_MODE_CONSOLE;

void elog_set_parseLine(char *line, char **lhs, char **rhs);
void elog_set_removeQuotes(char *str);
//Quotes must be the first and last characters.

void elog_set_removeQuotes(char *str)
{
	if (_password == NULL)
		_password = malloc(sizeof *_password);	//something to delete
	if (str[0] == '"') {
		int len = strlen(str);
		char *ret;
		ret = malloc((sizeof *ret) * (len - 1));
		str[len - 1] = '\0';
		strcpy(ret, str + 1);
		free(str);
		str = ret;
	}
}
void elog_set_parseLine(char *line, char **lhs, char **rhs)
{
	*lhs = NULL;
	*rhs = NULL;
	if (line == NULL)
		return;
	/*begin check for comment */
	char *lb = strstr(line, "#");
	if (lb != NULL) {
		int c = 0;
		for (c = 0; c < lb - line && (line[c] == ' ' ||
					      line[c] == '	'); ++c);
		if (c == lb - line)	//then it was commented
			return;
	}
	/*end check for comment */



	int size = strlen(line);
	int eq = strstr(line, "=") - line;	//index of '='

	if (eq < 0)		//Checking if the "=" was found
		return;

	line[eq] = '\0';
	char *l;
	l = malloc((sizeof *l) * (eq + 1));
	l[0] = '\0';

	strcpy(l, line);	//copy up to '='


	line[eq] = '=';
	char *t = elog_sp_whiteSpaceRemove(l);
	free(l);
	*lhs = t;

	char *r;
	r = malloc((sizeof *r) * (size - eq));
	r[0] = '\0';
	strcpy(r, line + eq + sizeof(char));	//copy from the '='
	t = elog_sp_whiteSpaceRemove(r);
	free(r);
	*rhs = t;

	return;
}

void elog_set_loadSettings(const char *fileName)
//pre: fileName exists and is a valid file location
//post:  Settings will be loaded into global variables
//              True is returned for success, false for any error
{
	char *x = getenv("HOME");
	char *y = "/.ejourn/ejourn.conf";

	if (fileName == NULL) {
		int size = (strlen(x) + strlen(y));
		_confPath = malloc((sizeof *_confPath) * size + 1);
		_confPath[0] = '\0';
		strcpy(_confPath, x);
		strcat(_confPath, y);

		fileName = _confPath;
		elog_sp_cat(&_path, x, "/.ejourn/MyJournal/", NULL);
	} else
		elog_sp_cat(&_confPath, fileName, NULL);



	struct elog_io_file *config =
	    elog_io_initialize(fileName, ELOG_IO_READ);
	/*initialize db */
	_str_name = malloc((sizeof *_str_name) * _STR_DB_MAX);
	_str_data = malloc((sizeof *_str_data) * _STR_DB_MAX);

	int c;
	for (c = 0; c < _STR_DB_MAX; ++c)
		_str_name[c] = _str_data[c] = NULL;	//initialize
	_str_size = 0;

	if (config == NULL) {
		//have to set this up manually
		elog_set_set_str("confPath", _confPath);
		return;
	}
	char *line;
	line = elog_io_read_realLine(config);



	while (line != NULL) {
		char *rhs;
		char *lhs;
		char *x = elog_sp_whiteSpaceRemove(line);
		free(line);
		line = x;
		elog_set_parseLine(line, &lhs, &rhs);

		if (lhs != NULL) {
			elog_set_removeQuotes(rhs);
			/*begin new database methods */
			if (strcmp(lhs, "extensions") != 0)	//we don't want extensions
			{
				elog_sp_cat(&(_str_name[_str_size]), lhs,
					    NULL);
				_str_data[_str_size] = rhs;
				++_str_size;
			}
			/*begin old backwards compat method */


			if (strcmp(lhs, "path") == 0) {
				free(_path);
				_path = rhs;
			} else if (strcmp(lhs, "encryption_method") == 0)
				_encryption_method = rhs;
			else if (strcmp(lhs, "height") == 0)
				_mainHeight = elog_sp_stringToShort(rhs);
			else if (strcmp(lhs, "width") == 0)
				_mainWidth = elog_sp_stringToShort(rhs);
			else if (strcmp(lhs, "tree_divider") == 0)
				_treeDivider = elog_sp_stringToShort(rhs);


			free(lhs);

		}

		free(line);
		line = elog_io_read_realLine(config);

	}			//end while


	elog_io_close(config);

}
void elog_set_writeSettings(const char *fileName)
{
	//Need to include functions to make the directory.
	//DIR *settingDirectory = opendir(fileName);
	//if (settingDirectory == NULL)
	//{
	//make directory
	//}

	struct elog_io_file *f =
	    elog_io_initialize(fileName, ELOG_IO_WRITE);
	elog_io_writeLine(f,
			  "#Do not add comments, they will be lost immediately after closing the program.\n",
			  0);
	elog_io_writeLine(f,
			  "#You may change the values for each variable, and it will be remembered\n",
			  0);

	//These methods of saving aren't needed
	//The new syste, handles this perfectly!
	/*elog_io_writeLine(f, "path=", 0);
	   elog_io_writeLine(f, _path, 0);
	   elog_io_writeLine(f, "\nencryption_method=", 0);
	   elog_io_writeLine(f, _encryption_method, 0);
	   elog_io_writeLine(f, "\nheight=", 0);
	   elog_io_writeLine(f, elog_sp_shortToString(_mainHeight),0);
	   elog_io_writeLine(f, "\nwidth=", 0);
	   elog_io_writeLine(f, elog_sp_shortToString(_mainWidth), 0);
	   elog_io_writeLine(f, "\ntree_divider=", 0);
	   elog_io_writeLine(f, elog_sp_shortToString(_treeDivider), 0);
	   elog_io_writeLine(f, "\n", 0);
	 */

	while (headExtention != NULL) {
		//begin-spitting out output
		elog_io_writeLine(f, "extension= \"", 0);
		elog_io_writeLine(f, headExtention->extension, 0);
		elog_io_writeLine(f, "\" \"", 0);
		elog_io_writeLine(f, headExtention->action, 0);
		elog_io_writeLine(f, "\"\n", 0);
		//**********end
		struct extProgram *p = headExtention;
		headExtention = headExtention->next;
		free(p);
	}
	int c;
	for (c = 0; _str_name[c] != NULL; ++c) {
		elog_io_writeLine(f, _str_name[c], 0);
		elog_io_writeLine(f, "=", 0);
		elog_io_writeLine(f, _str_data[c], 0);
		elog_io_writeLine(f, "\n", 0);
	}
	elog_io_close(f);
}
const char *elog_set_extAction(const char *extension)
{
	if (strcmp(extension, ".dry") == 0)
		return "native";
	struct extProgram *p = headExtention;
	while (p != NULL && strcmp(p->extension, extension) != 0)
		p = p->next;
	if (p != NULL)
		return p->action;
	else
		return NULL;
}
void elog_set_extAdd(char *extension, char *action)
//adds if extension isn't found if it is it changed the action
//to char *action
{
	if (_last != NULL && strcmp(_last->extension, extension) == 0) {
		_last->action = action;
		return;
	}
	struct extProgram *p = headExtention;
	while (p != NULL && strcmp(p->extension, extension) != 0)
		p = p->next;
	if (p == NULL) {
		p = malloc(sizeof *p);
		p->extension = extension;
		p->action = action;
		p->next = headExtention;
		headExtention = p;
	} else
		p->action = action;

}
const char *elog_set_encryptionMethod(char *method)
{
	if (method == NULL)
		return elog_set_get_str("encryption_method");
	elog_set_set_str("encryption_method", method);

	return NULL;
}


int elog_set_treeDivider(int *div)
{
	if (div == NULL)
		return elog_set_get_int("tree_divider");
	elog_set_set_int("tree_divider", *div);
	return 0;
}

int elog_set_mainHeight(int *height)
{
	if (height == NULL)
		return elog_set_get_int("height");
	elog_set_set_int("height", *height);
	return 0;
}
int elog_set_mainWidth(int *width)
{
	if (width == NULL)
		return elog_set_get_int("width");
	elog_set_set_int("width", *width);
	return 0;
}
const char *elog_set_confPath(char *confPath)
{//this function left out of standard settings intentionally.

	if (confPath == NULL)
		return _confPath;
	free(_confPath);
	_confPath = malloc((sizeof *_confPath) * strlen(confPath));
	strcpy(_confPath, confPath);
	return NULL;
}
const char *elog_set_path(char *path)
{
	if (path == NULL)
		return elog_set_get_str("path");
	elog_set_set_str("path", path);
	return NULL;
}



const char *elog_set_listExtensions(const char *ext)
{
	if (ext == NULL)
		return headExtention->extension;
	struct extProgram *p = headExtention;
	while (p != NULL) {
		if (strcmp(p->extension, ext) == 0)
			if (p->next != NULL)
				return p->next->extension;
		p = p->next;
	}
	return NULL;		//we didn't find it
}
int elog_set_mode(int *mode)
{
	if (mode == NULL)
		return elog_set_mode_current;
	else
		elog_set_mode_current = *mode;
	return 0;
}
const char *elog_set_currentFile(const char *name,
				 struct dict **meta)
{
	if (name == NULL) {
		*meta = elog_set_currentMeta;
		return elog_set_current;
	} else {
		if (elog_set_currentMeta != *meta
		    && elog_set_currentMeta != NULL)
			dict_unref(elog_set_currentMeta);
		elog_set_currentMeta = *meta;
		dict_ref(*meta);
	}
	return NULL;
}
const char *elog_set_get_str(const char *name)
//Currently a linear search
//Should later be replaced with a binary search
{
	int c;
	for (c = 0; _str_name[c] != NULL; ++c)
		if (strcmp(name, _str_name[c]) == 0)
			return _str_data[c];	//finding name
	return NULL;
}
void elog_set_set_str(const char *name, const char *data)
{
	int c;
	for (c = 0; _str_name[c] != NULL; ++c)
		if (strcmp(name, _str_name[c]) == 0) {
			free(_str_data[c]);
			elog_sp_cat(&(_str_data[c]), data, NULL);
			return;
		}
	elog_sp_cat(&(_str_name[c]), name, NULL);
	elog_sp_cat(&(_str_data[c]), data, NULL);
}
int elog_set_get_int(const char *name)
{
	const char *dat = elog_set_get_str(name);
	if (dat == NULL)
		return -1;
	return elog_sp_stringToShort(dat);

}
void elog_set_set_int(const char *name, int data)
{
	char *dat = elog_sp_shortToString(data);
	elog_set_set_str(name, dat);
	free(dat);
}







#endif
